import  dispatch
from copy import deepcopy
from mnemoply._renewed_lib.widgets import DataGridWidget, ApplyToAllWidget,  AutoCompleteField, \
    TextWithHelperField, CalendarDatePicker, Label, HiddenField, CheckBox, TextField, TextArea


class Entity(dict):                                
    def __getattr__(self, key):
        try: 
             return self[key]  
        except KeyError, k:                         
             raise AttributeError, k 
    
    def __setattr__(self, key, value):              
        self[key] = value                           
 
    def __delattr__(self, key):                      
        try:                                        
            del self[key]
        except KeyError, k: 
            raise AttributeError, k
 
    def __repr__(self):                             
        return self.__class__.__name__ + "(" + dict.__repr__(self) + ")"

class ParamsColumn:
    """Simple struct that describes single DataGrid column.

    Column has:
      - a name, which allows to uniquely identify column in a DataGrid
      - getter, which is used to extract field's value
      - title, which is displayed in the table's header
      - widget, which is used for display
      - params, which is used for create widget
    """

    def __init__(self, name, getter=None, title=None, widget=TextArea, params={}):
        if getter:
            if callable(getter):
                self.getter = getter
            else: # assume it's an attribute name
                self.getter = ParamsGrid.attrwrapper(getter)
        else:
            self.getter = ParamsGrid.attrwrapper(name)
        self.name = name
        self.title = title or name.replace('_',' ').capitalize()
        self.widget = widget
        if widget == HiddenField:
            self.title = ' '
        self.params = params

    def get_value_from_form(self,name,kw):
        result = None
        if hasattr( self.widget,'get_value_from_form'):
            return self.widget.get_value_from_form(name,kw)
        else:
            return kw[name] if kw.has_key(name) else None 

    def get_apply_widget(self):
        return ApplyToAllWidget(self.name,self.widget,**self.params)

    def get_field(self, row):
        return self.getter(row)
    def __str__(self):
        return "<Column %s>" % self.name

class ParamsGrid():
    columns=[]

    def __init__(self, columns=None):
        names = []
        self.columns = columns
        for col in self.columns:
            if col.name in names:
                raise ValueError('Duplicate column name: %s' % col.name)
            names.append(col.name)
        self.columns = columns
       
    def get_default_rows(self,objs,get_row=None):
        def get_default(objs):
            return objs
        
        if not get_row:
            get_row = get_default
        return [(obj.id, get_row(obj)) for obj in objs]
    
    def get_grid_widget(self,objs,get_row=None):
        def getter(col_name):
            return lambda(row):row[col_name]
        
        records = []
        visible_cols = [col for col in self.columns if not issubclass(col.widget, HiddenField)]

        first = {}
        for col in visible_cols:
            widget = col.get_apply_widget()
            first[col.name]=widget
        records.append(first)
        fields = [(col.title,getter(col.name)) for col in visible_cols ] 
        rows=self.get_default_rows(objs,get_row)
        ids = ','.join([str(row[0]) for row in rows])
        hidden_fields=[HiddenField(name="ids", default=ids)]
        
        for row in rows:
            record={}
            for col in self.columns:
                prms = deepcopy(col.params)
                if not prms.has_key('default'):
                    prms['default'] = col.get_field(row[1])
                name_widget = "%s_%s" %(col.name,row[0])
                widget = col.widget(name=name_widget,**prms)
                if issubclass(col.widget, HiddenField):
                    hidden_fields +=[widget]
                else:
                    record[col.name]=widget
            records.append(record)
        grid_widget = DataGridWidget(fields=fields, default=records,hidden_fields=hidden_fields)
        return grid_widget

    def get_wrapper(self,  kw):
        data = {}
        ids = kw['ids'] or ' '
        
        for num in ids.split(','):
            ent = {}
            for field in self.columns:
                key = "%s_%s"%(field.name,num)
                new_key = field.name
                value = field.get_value_from_form(key,kw)
                ent[new_key] = value
            data[num] = ent
        return data



    #def get_column(self, name):
    #    """Returns DataGrid.Column with specified name.
    #    Raises KeyError if no such column exists.
    #    """
    #    for col in self.columns:
    #        if col.name == name:
    #            return col
    #    raise KeyError(name)
    #def __getitem__(self, name):
    #    """Shortcut to get_column."""
    #    return self.get_column(name)
    #def get_field_getter(columns):
    #    """ Returns a function to access the fields of table by row, col """
    #    idx = {} # index columns by name
    #    for col in columns:
    #        idx[col.name] = col
    #    def _get_field(row, col):
    #        print 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
    #        print row
    #        return idx[col].get_field(row)
    #    
    #    return _get_field
    #get_field_getter = staticmethod(get_field_getter)

    class attrwrapper:
        """Helper class that returns an object's attribute when called.
        This allows to access 'dynamic' attributes (properties) as well as
        simple static ones.
        """
        def __init__(self, name):
            assert isinstance(name, str)
            self.name = name
        def __call__(self, obj):
            return getattr(obj, self.name)





